{
  buildDunePackage,
  lib,
  cppo,
  stdlib-shims,
  ppx_yojson_conv_lib,
  ocaml-syntax-shims,
  jsonrpc,
  omd,
  octavius,
  dune-build-info,
  dune-rpc,
  uutf,
  dyn,
  re,
  stdune,
  chrome-trace,
  csexp,
  result,
  pp,
  cmdliner,
  ordering,
  ocamlformat-rpc-lib,
  ocaml,
  version ?
    if lib.versionAtLeast ocaml.version "5.4" then
      "1.24.0"
    else if lib.versionAtLeast ocaml.version "5.3" then
      "1.23.1"
    else if lib.versionAtLeast ocaml.version "5.2" then
      "1.21.0"
    else if lib.versionAtLeast ocaml.version "4.14" then
      "1.18.0"
    else if lib.versionAtLeast ocaml.version "4.13" then
      "1.10.5"
    else if lib.versionAtLeast ocaml.version "4.12" then
      "1.9.0"
    else
      "1.4.1",
}:

let
  jsonrpc_v = jsonrpc.override {
    inherit version;
  };
in
buildDunePackage rec {
  pname = "lsp";
  inherit (jsonrpc_v) version src;
  minimalOCamlVersion = if lib.versionAtLeast version "1.7.0" then "4.12" else "4.06";

  # unvendor some (not all) dependencies.
  # They are vendored by upstream only because it is then easier to install
  # ocaml-lsp without messing with your opam switch, but nix should prevent
  # this type of problems without resorting to vendoring.
  preBuild = lib.optionalString (lib.versionOlder version "1.10.4") ''
    rm -r ocaml-lsp-server/vendor/{octavius,uutf,omd,cmdliner}
  '';

  buildInputs =
    if lib.versionAtLeast version "1.12.0" then
      [
        pp
        re
        ppx_yojson_conv_lib
        octavius
        dune-build-info
        dune-rpc
        omd
        cmdliner
        ocamlformat-rpc-lib
        dyn
        stdune
        chrome-trace
      ]
    else if lib.versionAtLeast version "1.10.0" then
      [
        pp
        re
        ppx_yojson_conv_lib
        octavius
        dune-build-info
        dune-rpc
        omd
        cmdliner
        ocamlformat-rpc-lib
        dyn
        stdune
      ]
    else if lib.versionAtLeast version "1.7.0" then
      [
        re
        octavius
        dune-build-info
        omd
        cmdliner
        ocamlformat-rpc-lib
      ]
    else
      [
        ppx_yojson_conv_lib
        ocaml-syntax-shims
        octavius
        dune-build-info
        omd
        cmdliner
      ];

  nativeBuildInputs = lib.optional (lib.versionOlder version "1.7.0") cppo;

  propagatedBuildInputs =
    if lib.versionAtLeast version "1.14.0" then
      [
        jsonrpc
        ppx_yojson_conv_lib
        uutf
      ]
    else if lib.versionAtLeast version "1.10.0" then
      [
        dyn
        jsonrpc
        ordering
        ppx_yojson_conv_lib
        stdune
        uutf
      ]
    else if lib.versionAtLeast version "1.7.0" then
      [
        csexp
        jsonrpc
        (pp.override { version = "1.2.0"; })
        ppx_yojson_conv_lib
        result
        uutf
      ]
    else
      [
        csexp
        jsonrpc
        ppx_yojson_conv_lib
        stdlib-shims
        uutf
      ];

  meta = jsonrpc.meta // {
    description = "LSP protocol implementation in OCaml";
  };
}
